﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls;

namespace Pavilion.DesignerTool.ViewTools
{
    /// <summary>
    /// Finds the shortest distance between two framework elements relative to the passed control
    /// </summary>
    public class PathFinder
    {
        /// <summary>
        /// Returns the shortest path between two FrameworkElements. The points are all relative to the passed in Panel
        /// </summary>
        public Geometry CalculatePath(FrameworkElement start, FrameworkElement end, Panel relativeTo)
        {
            Point startCenterRelativeToPanel = CalculateCenterRelativeToPanel(start, relativeTo);
            Point endCenterRelativeToPanel = CalculateCenterRelativeToPanel(end, relativeTo);

            //calculate delta y and delta x
            double deltaY = endCenterRelativeToPanel.Y - startCenterRelativeToPanel.Y;
            double deltaX = endCenterRelativeToPanel.X - startCenterRelativeToPanel.X;

            //if deltaY is negative then we're going to the top, otherwise we go to the bottom.
            //if deltaX is negative then we're going to the right, otherwise go to the left.

            bool linePassesThroughBottomOfStartAndTopOfEnd = deltaY > 0;
            bool linePassesThroughRightOfStartAndLeftOfEnd = deltaX > 0;

            //determine s and e by finding the points of intersection of the appropriate lines
            //construct the appropriate lines h1/w1 and h2/w2 based on the deltaY and deltaX values.

            //cases for deltaY:
                //deltaY > 0 w1 = bottom of start, w2 = top of end

           



                //deltaY < 0 w1 = top of start, w2 = bottom of end






            //cases for deltaX: 
                //deltaX > 0 

            //check the intersections. 

            throw new NotImplementedException();
        }

        private Point CalculateCenterRelativeToPanel(FrameworkElement frameworkElement, Panel relativeTo)
        {
            Point center = new Point(frameworkElement.ActualWidth / 2, frameworkElement.ActualHeight / 2);

            GeneralTransform transformToPanelCoordinates = frameworkElement.TransformToAncestor(relativeTo);
            return transformToPanelCoordinates.Transform(center);
        }

        private LineVector Return_w1(double deltaY, Point center, double width, double height)
        {
            //special case that line does not pass through top or bottom.
            if (deltaY == 0)
            {
               
            }

            double startX = center.X - width / 2;
            double endX = center.X + width / 2;
            double Y = deltaY > 0 ? center.Y + height / 2 : center.Y - height / 2;

            Vector positionVectorStart = new Vector(startX, Y);
            Vector positionVectorEnd = new Vector(endX, Y);

            return new LineVector(positionVectorStart, positionVectorEnd - positionVectorStart);
        }

        private LineVector ReturnH1(double deltaX, Point center, double width, double height)
        {
            throw new NotImplementedException();

            //special case that line does not pass through right or left. 
            if (deltaX == 0)
            {
                //return null;
            }

            double startY = center.Y + height / 2;
            double endY = center.Y - height / 2;
            double X = deltaX > 0 ? center.X + width / 2 : center.X - width / 2;

            Vector positionVectorStart = new Vector(X, startY);
            Vector positionVectorEnd = new Vector(X, startY);

            return new LineVector(positionVectorStart, positionVectorEnd - positionVectorStart);
        }


    }

    //vector equation of a line. 
    // <r> = <r0> + t<b>. If you don't understand this, go learn Calc III!
    public struct LineVector
    {
        public Vector PosToPointOnLine { get; set; }
        public Vector VectorAlongLineToEnd { get; set; }        

        public LineVector(Vector a, Vector b) : this()
        {
            PosToPointOnLine = a;
            VectorAlongLineToEnd = b;          
        }

        public static bool Intersects(LineVector firstLine, LineVector secondLine)
        {
            Vector deltaPosToPointOnLine = secondLine.PosToPointOnLine - firstLine.PosToPointOnLine;

            double t = Determinant(deltaPosToPointOnLine, secondLine.VectorAlongLineToEnd)/Determinant(firstLine.VectorAlongLineToEnd, secondLine.VectorAlongLineToEnd);
            double u = Determinant(deltaPosToPointOnLine, firstLine.VectorAlongLineToEnd) / Determinant(firstLine.VectorAlongLineToEnd, secondLine.VectorAlongLineToEnd);

            bool isTBetweenZeroAndOne = t <= 1 && t >= 0;
            bool isUBetweenZeroAndOne = u <= 1 && u >= 0;

            return isTBetweenZeroAndOne && isUBetweenZeroAndOne;
        }

        public static double Determinant(Vector firstVector, Vector secondVector)
        {
            return firstVector.X * secondVector.Y - firstVector.Y * secondVector.X;
        }

        
    }

   

}
